﻿using System;
using System.Collections.Generic;
using System.Text;
using HR.Appointments.DataLayer;
using HR.Appointments.Service.ValueObjects;

namespace HR.Appointments.Service
{
    /// <summary>
    /// Entity class for orders
    /// </summary>
    public class OrderEntity
    {
        #region Member variable
        private int _appointmentId;
        //private int _actvitityId;
        private DateTime _creationDate;
        private DateTime _bookingDate;
        private TimeUnit _bookingTime = TimeUnit.Create(0, 0);
        private int _duration;
        private int _orderStatus;
        private WorkstationEntity _workstation;
        private Customer _customer;
        private CompanyEntity _company;
        private ActivityEntity _activity;
        private int _workstationId;
        private bool _isSent;
        #endregion

        #region Constructors
        private OrderEntity(int appointmentId, int companyId, DateTime creationDate, DateTime bookingDate,
            TimeUnit bookingTime, int orderstatus, int duration, Customer customer, 
            int activityId, int workstationId, bool isSent)
        {
            _workstation = DAO.Instance.Workstation.GetInstance(workstationId);
            _activity = DAO.Instance.Activity.GetInstance(activityId);
            _company = DAO.Instance.Company.GetInstance(companyId);

            System.Diagnostics.Debug.Assert(_company != null, "Company not loaded");
            System.Diagnostics.Debug.Assert(_activity != null, "Activity not loaded");
            System.Diagnostics.Debug.Assert(_workstation != null, "Workstation not loaded");

            _appointmentId = appointmentId;
            _creationDate = creationDate;
            _bookingDate = bookingDate;
            _orderStatus = orderstatus;
            _bookingTime = bookingTime;
            _duration = duration;
            _customer = customer;
            _workstationId = workstationId;
            _isSent = isSent;
            
        }
        #endregion

        #region Properties
        /// <summary>
        /// The unique id for the order
        /// </summary>
        public int AppointmentId
        {
            get 
            {
                return _appointmentId;
            }
        }

        /// <summary>
        /// The date when the order is to be processed
        /// </summary>
        public DateTime BookingDate
        {
            get
            {
                return _bookingDate; 
            }
            set
            {
                _bookingDate = value; 
            }
        }

        /// <summary>
        /// At what time the order starts
        /// </summary>
        public TimeUnit FromTime
        {
            get
            {
                return _bookingTime; 
            }
            set
            {
                _bookingTime = value; 
            }
        }

        /// <summary>
        /// At what time the order is finished
        /// </summary>
        public TimeUnit ToTime
        {
            get
            {
                try
                {
                    TimeUnit res = (TimeUnit)_bookingTime.Clone();
                    int duration = _duration / _company.SlotDuration;
                    for (int i = 0; i < duration; i++)
                    {
                        res.Add(_company.SlotDuration);
                    }
                    return res;
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return TimeUnit.Create(0, 0);
                }
            }
            set
            {
                _bookingTime = value;
            }
        }

        /// <summary>
        /// The duration the the order
        /// </summary>
        public int Duration
        {
            get
            {
                return _duration; 
            }
            set
            {
                _duration = value; 
            }
        }

        /// <summary>
        /// The status of the order 
        /// </summary>
        public OrderStatus Status
        {
            get
            {
                switch (_orderStatus)
                {
                    case 0: 
                        return OrderStatus.UNCONFIRMED;
                    case 1:
                        return OrderStatus.CONFIRMED;
                    case 2:
                        return OrderStatus.DENIED;
                    default:
                        return OrderStatus.UNCONFIRMED;
                }
            }
            set
            {
                switch (value)
                {
                    case OrderStatus.UNCONFIRMED:
                        _orderStatus = 0;
                        break;
                    case OrderStatus.CONFIRMED:
                        _orderStatus = 1;
                        break;
                    case OrderStatus.DENIED:
                        _orderStatus = 2;
                        break;
                }

            }
        }

        /// <summary>
        /// Information about the workstation handling the order
        /// </summary>
        public WorkstationEntity Station
        {
            get
            {
                return _workstation; 
            }
            set
            {
                _workstation = value; 
            }
        }

        /// <summary>
        /// Information about the activity the customer ordered
        /// </summary>
        public ActivityEntity Activity
        {
            get
            {
                System.Diagnostics.Debug.Assert(_activity != null, "Activity in OrderEntity is null");
                return _activity;
            }
            set
            {
                _activity = value;
            }
        }

        /// <summary>
        /// Information about the customer who orderd
        /// </summary>
        public Customer Person
        {
            get
            {
                return _customer; 
            }
            set
            {
                _customer = value; 
            }
        }

        /// <summary>
        /// Company that owns this order
        /// </summary>
        public CompanyEntity Company
        {
            get 
            {
                return _company;
            }
        }

        /// <summary>
        /// Id of the workstation who owns this order
        /// </summary>
        public int WorkstationId
        {
            get { return _workstationId; }
        }

        /// <summary>
        /// If the customer has been notified
        /// </summary>
        public bool IsSent
        {
            get
            {
                return _isSent;
            }
            set
            {
                _isSent = value;
            }
        }
        #endregion

        #region Internal Methods
        /// <summary>
        /// Convert this object to datalayer 
        /// </summary>
        /// <param name="data">Datalayer entity</param>
        /// <returns>A datalayer entity with this objects values</returns>
        internal Appointment ToData(Appointment data)
        {
            if (data == null)
            {
                data = new Appointment();
            }
            data.ActivityId = _activity.ActivityId;
            data.IsBooked = _orderStatus;
            data.BookingDate = _bookingDate;
            data.BookingHour = _bookingTime.Hour;
            data.BookingMinute = _bookingTime.Minute;
            data.CompanyId = _company.CompanyId;
            data.CreationDate = _creationDate;
            data.Duration = _duration;
            data.Email = _customer.Email;
            data.Name = _customer.Name;
            data.Phone = _customer.Phone;
            data.WorkstationId = _workstation.WorkstationId;
            data.Booked = _isSent;
            return data;
        }
        #endregion

        #region Override Methods
        /// <summary>
        /// Returns a String that represents the current Object.
        /// </summary>
        /// <returns>A String that represents the current Object.</returns>
        public override string ToString()
        {
            return _customer.Phone + " " + _customer.Name + " " +
                _bookingDate.ToShortDateString() + " " +
                _bookingTime.ToString() + " " + _orderStatus.ToString();
        }
        #endregion

        #region Static Methods
        /// <summary>
        /// Loads a datalayer entity into a service entity.
        /// </summary>
        /// <param name="row"></param>
        /// <returns>A loaded entity</returns>
        internal static OrderEntity Load(HR.Appointments.DataLayer.Appointment row)
        {
            if (row == null) return null;

            int stationId = Convert.ToInt32(row.WorkstationId.Value);
            return new OrderEntity(row.AppointmentId, row.CompanyId, row.CreationDate, row.BookingDate,
                TimeUnit.Create(row.BookingHour, row.BookingMinute), row.IsBooked,
                row.Duration, Customer.Create(row.Name, row.Phone, row.Email), 
                row.ActivityId, stationId, row.Booked);
        }

        /// <summary>
        /// Creates a new entity
        /// </summary>
        /// <param name="companyId">The company identifier</param>
        /// <param name="creationDate">The date which the order was created</param>
        /// <param name="bookingDate">The date when the order should be processed</param>
        /// <param name="bookingTime">The time when the order should be processed</param>
        /// <param name="orderstatus">The status of the order 0=unconfirm, 1=confirmed, 2=denied</param>
        /// <param name="customer">Customer information</param>
        /// <param name="activityId">The activity identifier</param>
        /// <param name="workstationId">The workstation indentifier</param>
        /// <returns></returns>
        public static OrderEntity Create(int companyId, DateTime creationDate, DateTime bookingDate,
            TimeUnit bookingTime, int orderstatus, Customer customer, 
            int activityId, int workstationId)
        {
            var activity = DAO.Instance.Activity.GetInstance(activityId);

            System.Diagnostics.Debug.Assert(activity != null, "Activity is null");

            return new OrderEntity(0, companyId, creationDate, bookingDate, bookingTime, orderstatus, 
                activity.Duration, customer, activityId, workstationId, false);
        }
        #endregion
    }
}
